﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Media;

namespace SilverMindMap.Core.Model
{
    public class Node : ObservableObject
    {
        public static readonly Color DefaultForegroundColor = Colors.Black;
        public static readonly Color DefaultBackgroundColor = Colors.White;

        private Color _backgroundColor;
        private Color _foregroundColor;        
        private string _caption;
        private Uri _hyperlink;
        private MindMap _mindMap;
        private readonly ObservableCollection<Link> _links;
        private readonly ReadOnlyObservableCollection<Link> _linksView;

        public Node()
            : this("")
        { }

        public Node(string caption)
        {
            _backgroundColor = DefaultBackgroundColor;
            _foregroundColor = DefaultForegroundColor;
            _caption = caption ?? "";
            _hyperlink = null;            
            _links = new ObservableCollection<Link>();
            _linksView = new ReadOnlyObservableCollection<Link>(_links);
        }

        public Color BackgroundColor
        {
            get { return _backgroundColor; }
            set
            {
                if (_backgroundColor == value)
                    return;

                _backgroundColor = value;
                RaisePropertyChanged("BackgroundColor");

            }
        }

        public Color ForegroundColor
        {
            get { return _foregroundColor; }
            set
            {
                if (_foregroundColor == value)
                    return;

                _foregroundColor = value;
                RaisePropertyChanged("ForegroundColor");
            }
        }

        public Uri Hyperlink
        {
            get { return _hyperlink; }
            set
            {
                if (_hyperlink == value)
                    return;

                _hyperlink = value;
                RaisePropertyChanged("Hyperlink");
            }
        }

        public string Caption
        {
            get { return _caption; }
            set
            {
                if (_caption == value)
                    return;

                _caption = value ?? string.Empty;
                RaisePropertyChanged("Caption");
            }
        }

        public MindMap MindMap
        {
            get { return _mindMap; }
            set
            {
                if (_mindMap == value)
                    return;

                _mindMap = value;
                RaisePropertyChanged("MindMap");
            }
        }

        public override string ToString()
        {
            return string.Format("Node {0}", _caption);
        }

        #region Links

        public ReadOnlyObservableCollection<Link> Links
        {
            get { return _linksView; }
        }

        public Link GetLink(Node other)
        {
            return _links.FirstOrDefault(link => link.FirstNode == other || link.SecondNode == other);
        }

        public Link AddLink(Node linkedNode)
        {
            Guard.ArgumentNotNull(linkedNode, "linkedNode");
            if (GetLink(linkedNode) != null)
                throw new ArgumentException("Given node is already linked", "linkedNode");

            var link = new Link(this, linkedNode);

            this.AddLinkWithoutVerification(link);
            linkedNode.AddLinkWithoutVerification(link);

            return link;
        }

        public bool RemoveLink(Node linkedNode)
        {
            return RemoveLink(GetLink(linkedNode));
        }

        public bool RemoveLink(Link link)
        {
            if (!_links.Contains(link))
                return false;

            this.RemoveLinkWithoutVerification(link);
            if (this == link.FirstNode)
                link.SecondNode.RemoveLinkWithoutVerification(link);
            else
                link.FirstNode.RemoveLinkWithoutVerification(link);

            return true;
        }

        protected virtual void AddLinkWithoutVerification(Link link)
        {
            _links.Add(link);
        }

        protected virtual void RemoveLinkWithoutVerification(Link link)
        {
            _links.Remove(link);
        }

        #endregion        
    }
}
